/*
 * RobonetDocumentManager.java is part of htn-example.
 *
 * RobonetDocumentManager.java is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * RobonetDocumentManager.java is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with RobonetDocumentManager.java.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.htn.telescopes.repository;

import java.rmi.Naming;
import java.util.Date;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.PrintWriter;

import ngat.util.logging.Logger;
import ngat.util.logging.Logging;

import org.htn.repository.DefaultDocumentManager;
import org.htn.repository.DocumentManager;
import org.htn.telescopes.rtml.ConfigurationManager;
import org.htn.telescopes.rtml.ObservationIDMapper;
import org.htn.telescopes.rtml.parser.RTMLCreate;
import org.htn.telescopes.rtml.parser.RTMLDocument;
import org.htn.telescopes.rtml.parser.RTMLException;
import org.htn.telescopes.rtml.parser.RTMLIntelligentAgent;

public class RobonetDocumentManager extends DefaultDocumentManager implements Logging
{
	protected Logger traceLog;

	/**
	 * Create an error (type = 'reject' from scratch).
	 * @param rejectionReason The reason the abort request was rejected. Must be a standard string from 
	 *       RTMLHistoryEntry.
	 * @param errorMessage The error messsage.
	 * @see org.estar.rtml.RTMLHistoryEntry
	 */
	public String createErrorDocReply(String rejectionReason,String errorMessage)
	{
		RTMLDocument document = new RTMLDocument();

		// document version must be set - assume legacy version atm
		document.setVersion(RTMLDocument.RTML_VERSION_22);
		return createErrorDocReply(document,rejectionReason,errorMessage);
	}
    
	/** Create an error (type = 'reject' from supplied document.
	 * @param document The document to change to error type.
	 * @param rejectionReason The reason the abort request was rejected. Must be a standard string from 
	 *       RTMLHistoryEntry.
	 * @param errorMessage The error messsage.
	 * @see org.estar.rtml.RTMLHistoryEntry
 	 */
	public String createErrorDocReply(RTMLDocument document,String rejectionReason,String errorMessage)
	{
		document.setCompletionTime(new Date());
		try
		{
			document.setReject();
			document.addHistoryRejection("EmbeddedAgent:"+this.generateId(),null,rejectionReason,errorMessage);
			document.setErrorString(errorMessage); 
		} 
		catch (RTMLException rx)
		{
			rx.printStackTrace();
			System.err.println("Error setting error string in doc: "+rx);
		}
		return createReply(document);	   
	}
    
	/** Creates a reply message from the supplied document.
	 * @param document The document to extract a reply message from.
	 * @return A reply message in RTML format.
	 */
	public String createReply(RTMLDocument document)
	{
		//System.err.println("Create reply for: \n\n\n"+document+"\n\n\n");
		try {
			RTMLCreate createReply = new RTMLCreate();
			createReply.create(document);
	    
			String replyMessage = createReply.toXMLString();
			createReply = null;
			return replyMessage;
		} catch (Exception ex) {
			System.err.println("Error creating RTMLDocument: "+ex);
			return null;
		}
	}
    
	/** 
	 * Send a reply of specified type. This differs from sendDoc(doc,type) in that
	 * an io client connection is made to the intelligent agent using the information in the
	 * documents intelligent agent tag, rather than replying to an agent request.
	 * This method is used by the UpdateHandler to send update messages.
	 * @param document The document to send.
	 * @param type     A string denoting the type of document to send.
	 * @see #createReply
	 * @see #logRTML
	 */
	public void sendDocumentToIA(RTMLDocument document) throws Exception
	{
		String documentUId = null;

		if(document != null)
			documentUId = document.getUId();
		if(documentUId == null)
			documentUId = new String("Unknown");
		traceLog.log(INFO, 1,ConfigurationManager.CLASS, "sendDocumentToIA("+documentUId+") Started.");

		switch (ConfigurationManager.getManager().getAsyncResponseMode())
		{
			case ConfigurationManager.ASYNC_MODE_RMI:
				NodeAgentAsynchronousResponseHandler narh = (NodeAgentAsynchronousResponseHandler)
					Naming.lookup("rmi://"+ConfigurationManager.getManager().getNarHost()+"/NAAsyncResponseHandler");
 
				if (narh == null)
				{
					traceLog.log(INFO, 1, ConfigurationManager.CLASS, "sendDocumentToIA("+documentUId+
						     "): NA ResponseHandler was null.");
					throw new Exception(this.getClass().getName()+":sendDocumentToIA("+
							    documentUId+"):Lookup [NAAsyncResponseHandler] was null.");
				}
				logRTML(traceLog,1,"sendDocumentToIA("+documentUId+"):",document);
				narh.handleAsyncResponse(document);

				traceLog.log(INFO, 1, ConfigurationManager.CLASS,"sendDocumentToIA("+documentUId+
					     "):Sent document successfully via NA ResponseHandler");
				break;
			case ConfigurationManager.ASYNC_MODE_FILE:
				// Write rtml object to file
				RTMLCreate refact = null;
				String resultString = null;
				try 
				{
					refact = new RTMLCreate();
					refact.setDoctypeSystemID(RTMLDocument.RTML_VERSION_31);
					refact.create(document);
					File outputFile = ConfigurationManager.getManager().getAsyncOutputFile();
					refact.toStream(new FileOutputStream(outputFile));
				} 
				catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				break;
			default:
		}
	}
	
	/**
	 * Log the RTML document. Create an XML String and log this with a description.
	 * All failures are caught and an error message logged instead.
	 * @param l The logger to log to.
	 * @param logLevel The log level.
	 * @param description A description of why we are logging the document.
	 * @param document The document to log.
	 * @see org.estar.rtml.RTMLCreate#create
	 * @see org.estar.rtml.RTMLCreate#toXMLString
	 */
	protected void logRTML(Logger l,int logLevel,String description,RTMLDocument document)
	{
		RTMLCreate create = null;
		String documentUId = null;
		String documentString = null;

		try
		{
			create = new RTMLCreate();
			documentUId = document.getUId();
			create.create(document);
			documentString = create.toXMLString();
			l.log(logLevel,description+documentString);
		}
		catch(Exception e)
		{
			l.log(logLevel, "logRTML:Failed to create XML String for document:"+documentUId+":"+e,e);
			e.printStackTrace();
		}
	}
}
